module semaphore_example;

    // 声明并初始化一个初始值为2的 semaphore (表示有2个资源可用)
    semaphore sem = new(2);

    // 定义共享资源 (共享计数器)
    int shared_counter = 0;

    // 访问共享资源的任务 (堵塞方式)
    task automatic access_resource(int id);
        $display("Process %0d: Attempting to access resource (blocking)", id);

        // 尝试获取资源 (阻塞方式)
        sem.get(1);
        $display("Process %0d: Acquired resource", id);

        // 模拟资源访问
        #5; shared_counter++;
        $display("Process %0d: Updated shared counter to %0d", id, shared_counter);

        // 释放资源
        sem.put(1);
        $display("Process %0d: Released resource", id);
    endtask

    // 访问共享资源的任务 (非堵塞方式)
    task automatic try_access_resource(int id);
        int retry_count = 0;
        int max_retries = 5;

        $display("Process %0d: Attempting to access resource (non-blocking)", id);

        while (retry_count < max_retries) begin
            // 尝试获取资源 (非阻塞方式)
            if (sem.try_get(1)) begin
                $display("Process %0d: Acquired resource (non-blocking, retry %0d)", id, retry_count);
                // 模拟访问资源
                #5; shared_counter++;
                $display("Process %0d: Updated shared counter to %0d", id, shared_counter);
                // 释放资源
                sem.put(1);
                $display("Process %0d: Released resource", id);
                break; // 成功获取资源后退出循环
            end
            else begin
                retry_count++;
                $display("Process %0d: Failed to acquire resource (retry %0d)", id, retry_count - 1);
                #($urandom_range(10, 30));  // 随机延迟后重试
            end
        end

        if (retry_count == max_retries) begin
            $display("Process %0d: Max retries reached. Giving up.", id);
        end
    endtask

    initial begin
        // 启动多个并发进程
        fork
            access_resource(1);     // 阻塞方式
            access_resource(2);     // 阻塞方式
            try_access_resource(3); // 非阻塞方式
            try_access_resource(4); // 非阻塞方式
        join
        $display("Final shared counter value: %0d", shared_counter);
    end

endmodule
